package com.hqd.jjvm.rtda.heap.ref;

import com.hqd.jjvm.rtda.heap.JClass;
import com.hqd.jjvm.rtda.heap.JField;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class JFieldRef extends JMemberRef {
	private JField jField;

	public JFieldRef(JFieldRef fieldRef) throws ClassNotFoundException {
		this(fieldRef.getJClass(), fieldRef.getClassName(), fieldRef.getName(), fieldRef.getDescriptor());
	}

	public JFieldRef(JClass refJClass, JFieldRef fieldRef) throws ClassNotFoundException {
		this(refJClass, fieldRef.getClassName(), fieldRef.getName(), fieldRef.getDescriptor());
	}

	public JFieldRef(JClass refJClass, String className, String fieldName, String descriptor) throws ClassNotFoundException {
		super(refJClass, className);
		newJFieldRef(fieldName, descriptor);

	}

	private void newJFieldRef(String fieldName, String descriptor) {
		setDescriptor(descriptor);
		setName(fieldName);
		this.jField = lookupField(this.getJClass(), fieldName, descriptor);
		/**
		 * 找不到对应的属性
		 */
		if (jField == null) {
			throw new NoSuchFieldError();
		}
		/**
		 * 没有权限访问
		 */
		if (jField == null) {
			throw new IllegalAccessError();
		}
	}

	private JField lookupField(JClass jClass, String fieldName, String descriptor) {
		for (JField jField : jClass.getJFields()) {
			if (equalsJField(jField, fieldName, descriptor)) {
				return jField;
			}
		}
		for (JClass interfaceJClass : jClass.getInterfaceClasses()) {
			JField jField = lookupField(interfaceJClass, fieldName, descriptor);
			if (jField != null) {
				return jField;
			}
		}
		if (jClass.getSuperClass() != null) {
			return lookupField(jClass.getSuperClass(), fieldName, descriptor);
		}
		return null;
	}

	protected boolean equalsJField(JField jField, String fieldName, String descriptor) {
		if (jField.getDescriptor().equals(descriptor) && jField.getName().equals(fieldName)) {
			return true;
		}
		return false;
	}
}
